check out this fascinating post by raph levien about how vsync works (defer swapping until scanout completes, but only block when actually writing to the new backbuffer), how double and triple buffering typically work, and how these techniques improve throughput at the expense of latency, jitter, and/or power consumption.
vsync means rendering and running your updates as early as possible, right after scanout completes. it’s simple, but it makes the frame you present as stale as possible.
“frame pacing” means rendering and running your updates as late as possible, right before the next scanout starts. it makes the frame you present as fresh as possible, but it’s more complicated, because you need to estimate how long your work will take.
see also, how the compositors we have today regress on latency compared to “racing the beam”.
see also, why it’s surprisingly hard to write an app that resizes smoothly on the left edge.